﻿using System;
using System.Diagnostics;
using System.Runtime.InteropServices;

//https://docs.microsoft.com/en-us/windows/win32/api/shellapi/ns-shellapi-notifyicondataw
namespace WPFDevelopers.Controls.Runtimes.Shell32
{
    [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Auto)]
    public struct NOTIFYICONDATA
    {
        //Size of this structure, in bytes.
        public uint cbSize;

        //Handle to the window that receives notification messages associated with an icon in the taskbar status area.
        public IntPtr hWnd;

        //Application-defined identifier of the taskbar icon. Values from 0 to 12 are reserved and should not be used
        public uint uTaskbarIconId;

        /// <summary>
        /// Flags that either indicate which of the other members of the structure contain valid data or provide 
        /// additional information to the tooltip as to how it should display. 
        /// This member can be a combination of the following values:
        /// </summary>
        public NIFFlags uFlags;


        /// <summary>
        /// An application-defined message identifier. 
        /// The system uses this identifier to send notification messages to the window identified in hWnd.
        /// These notification messages are sent when a mouse event or hover occurs in the bounding rectangle of the icon, when the icon is selected or activated with the keyboard, or when those actions occur in the balloon notification
        /// When the uVersion member is either 0 or NOTIFYICON_VERSION, the wParam parameter of the message contains the identifier of the taskbar icon in which the event occurred
        /// This identifier can be 32 bits in length. 
        /// he lParam parameter holds the mouse or keyboard message associated with the event.
        /// For example, when the pointer moves over a taskbar icon, lParam is set to WM_MOUSEMOVE.
        /// When the uVersion member is NOTIFYICON_VERSION_4, applications continue to receive notification events in the form of application-defined messages through the uCallbackMessage member,
        /// but the interpretation of the lParam and wParam parameters of that message is changed as follows:
        /// LOWORD(lParam) contains notification events, such as NIN_BALLOONSHOW, NIN_POPUPOPEN, or WM_CONTEXTMENU.
        /// HIWORD(lParam) contains the icon ID. Icon IDs are restricted to a length of 16 bits.
        /// GET_X_LPARAM(wParam) returns the X anchor coordinate for notification events NIN_POPUPOPEN, NIN_SELECT, NIN_KEYSELECT, and all mouse messages between WM_MOUSEFIRST and WM_MOUSELAST. If any of those messages are generated by the keyboard, wParam is set to the upper-left corner of the target icon. For all other messages, wParam is undefined.
        /// GET_Y_LPARAM(wParam) returns the Y anchor coordinate for notification events and messages as defined for the X anchor.
        /// </summary>
        public uint uCallbackMessage;

        /// <summary>
        /// t is recommended that you provide both a 16x16 pixel icon and a 32x32 icon in your resource file.
        /// Use LoadIconMetric to ensure that the correct icon is loaded and scaled appropriately.
        /// </summary>
        public IntPtr hIcon;

        /// <summary>
        /// For Windows 2000 and later, szTip can have a maximum of 128 characters, including the terminating null character
        /// </summary>
        [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 128)]
        public string szTip;

        /// <summary>
        /// The state of the icon. One or both of the following values:
        /// </summary>
        public NISFlags dwState;

        /// <summary>
        /// A value that specifies which bits of the dwState member are retrieved or modified. 
        /// The possible values are the same as those for dwState. 
        /// For example, setting this member to NIS_HIDDEN causes only the item's hidden state to be modified while the icon sharing bit is ignored regardless of its value
        /// </summary>
        public NISFlags dwStateMask;

        /// <summary>
        /// A null-terminated string that specifies the text to display in a balloon notification.
        /// It can have a maximum of 256 characters, including the terminating null character, but should be restricted to 200 characters in English to accommodate localization. 
        /// To remove the balloon notification from the UI, either delete the icon (with NIM_DELETE) or set the NIF_INFO flag in uFlags and set szInfo to an empty string.
        /// </summary>
        [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 256)]
        public string szInfo;

        /// <summary>
        /// a union which timeout or version
        /// This member is deprecated as of Windows Vista. Notification display times are now based on system accessibility settings.
        /// Timeout
        /// The timeout value, in milliseconds, for notification. The system enforces minimum and maximum timeout values. 
        /// Values specified in uTimeout that are too large are set to the maximum value.
        /// Values that are too small default to the minimum value.
        /// The system minimum and maximum timeout values are currently set at 10 seconds and 30 seconds,respectively.
        /// Version
        /// Specifies which version of the Shell notification icon interface should be used.
        /// For more information on the differences in these versions, see Shell_NotifyIcon.
        /// This member is employed only when using Shell_NotifyIcon to send an NIM_SETVERSION message.
        /// </summary>
        public uint TimeoutOrVersion;

        /// <summary>
        /// A null-terminated string that specifies a title for a balloon notification.
        /// This title appears in a larger font immediately above the text. It can have a maximum of 64 characters, 
        /// including the terminating null character, 
        /// but should be restricted to 48 characters in English to accommodate localization.
        /// </summary>
        [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 64)]
        public string szInfoTitle;


        public NIIFFlags dwInfoFlags;

        /// <summary>
        /// Windows 7 and later: A registered GUID that identifies the icon. 
        /// This value overrides uID and is the recommended method of identifying the icon. 
        /// The NIF_GUID flag must be set in the uFlags member.
        /// Windows XP and Windows Vista: Reserved; must be set to 0.
        /// 
        /// If your application is intended to run on both Windows Vista and Windows 7, 
        /// it is imperative that you check the version of Windows and only specify a nonzero guidItem if on Windows 7 or later.
        /// </summary>
        //public Guid guidItem;

        /// <summary>
        /// Windows Vista and later. The handle of a customized notification icon provided by the application that should be used independently of the notification area icon. 
        /// If this member is non-NULL and the NIIF_USER flag is set in the dwInfoFlags member, this icon is used as the notification icon. 
        /// If this member is NULL, the legacy behavior is carried out.
        /// </summary>
        //public IntPtr hBalloonIcon;

        public static NOTIFYICONDATA GetDefaultNotifyData(IntPtr hWnd)
        {
            var vNotifyData = new NOTIFYICONDATA();

            if (Environment.OSVersion.Version.Major >= 6)
            {
                vNotifyData.cbSize = (uint)Marshal.SizeOf(vNotifyData);
                vNotifyData.TimeoutOrVersion = (uint)NOTIFYICONVERSIONFlags.NOTIFYICON_VERSION_4;
            }
            else
            {
                vNotifyData.cbSize = (uint)NOTIFYICONDATAWFlags.NOTIFYICONDATA_V3_SIZE; // NOTIFYICONDATAW_V3_SIZE
                vNotifyData.TimeoutOrVersion = (uint)TimeOutFlags.Minimum_Timeout;
            }

            vNotifyData.hWnd = hWnd;
            vNotifyData.uCallbackMessage = (uint)NOTIFYMESSAGESINK.NotifyCallBackMessage;

            vNotifyData.dwState = NISFlags.NIS_HIDDEN;
            vNotifyData.dwStateMask = NISFlags.NIS_HIDDEN;

            vNotifyData.uFlags = NIFFlags.NIF_MESSAGE | NIFFlags.NIF_ICON | NIFFlags.NIF_TIP;

            vNotifyData.szTip = Process.GetCurrentProcess().ProcessName;
            vNotifyData.szInfo = string.Empty;
            vNotifyData.szInfoTitle = string.Empty;

            return vNotifyData;
        }


    }
}
